package jp.co.cos.ittrick.channel.service;

import java.util.Date;
import java.util.List;

import jp.co.cos.ittrick.channel.Constants;
import jp.co.cos.ittrick.channel.common.exception.DatastorePutException;
import jp.co.cos.ittrick.channel.common.exception.DoubleInsertException;
import jp.co.cos.ittrick.channel.meta.ApplicationModelMeta;
import jp.co.cos.ittrick.channel.model.ApplicationModel;

import org.slim3.datastore.Datastore;
import org.slim3.memcache.Memcache;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Transaction;


public class ApplicationService {

    /**
     * ApplicationModel の取得
     * @param pkKey
     * @return ApplicationModel
     */
    public ApplicationModel getApplicationModel() {

        ApplicationModel model = Memcache.get(Constants.APPLICATION_MEMCACHE_KEY);
        if(model != null) return model;

        ApplicationModelMeta meta = new ApplicationModelMeta();
        List<ApplicationModel> applModelList = Datastore.query(meta).asList();

        if(applModelList != null && applModelList.size() > 0) {
            model = applModelList.get(0);
            if(model != null) Memcache.put(Constants.APPLICATION_MEMCACHE_KEY, model);

            return model;
        }
        return null;
    }

    /**
     * Insert
     * @param pkKey
     * @param model
     * @return key
     * @throws DoubleInsertException
     * @throws DatastorePutException
     */
    public Key insert(ApplicationModel model)
    throws DoubleInsertException, DatastorePutException {

        // ２重登録チェック
        if(getApplicationModel() != null) {
            throw new DoubleInsertException();
        }

        model.setLastmod(new Date());

        // キーの作成
        Key key = null;

        // insert
        Transaction tx = Datastore.beginTransaction();
        try {
            key = Datastore.put(tx, model);
            tx.commit();
        }
        catch (Exception e) {
            if (tx.isActive()) {
                tx.rollback();
            }
            throw new DatastorePutException();
        }

        return key;
    }


    /**
     * Update
     * @param model
     * @throws DatastorePutException
     */
    public void update(ApplicationModel model) throws DatastorePutException {

        model.setLastmod(new Date());

        // Local Transaction の開始
        Transaction tx = Datastore.beginTransaction();

        try {
            // バージョンによる変更チェック
            Datastore.get(tx, ApplicationModelMeta.get(), model.getKey(), model.getVersion());
            // 更新
            Datastore.put(tx, model);

            tx.commit();

            // Memcacheを削除する
            Memcache.delete(model.getKey());

        }catch (Exception e) {
            if (tx.isActive()) {
                tx.rollback();
            }
            throw new DatastorePutException();
        }
    }

    /**
     * 削除
     * @param serialPkKey
     * @param articleNum
     * @param articlePageNum
     * @throws Exception
     */
    public void delete(String pkKey) throws Exception {

        ApplicationModel applicationModel = getApplicationModel();
        Key pageKey = applicationModel.getKey();

        // Local Transaction の開始
        Transaction tx = Datastore.beginTransaction();

        try {
            Datastore.delete(tx, pageKey);

            tx.commit();

        }catch (Exception e) {
            if (tx.isActive()) {
                tx.rollback();
            }
            throw e;
        }
    }

}
